﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Hydra.Shell.Interfaces;
using System.Collections.Specialized;
using System.Xml.Linq;
using HydraShellServer.Implementations;
using System.Windows.Browser;
using Hydra.Shell.Implementations;

namespace Hydra.Shell.EntityPaths
{
    public enum PathObjectType
    {
        Package,
        Service
    }

    public class PathRoot
    {
        public event EventHandler Disposed;
        public Guid InstanceID { get; private set; }
        public Guid ObjectGuid { get; private set; }
        public PathObjectType ObjectType { get; private set; }
        private ISynchronousProxy synchronousProxy;

        public PathRoot(IHydraPackage package, ISynchronousProxy synchronousProxy)
        {
            InstanceID = Guid.NewGuid();
            ObjectGuid = package.PackageGuid;
            ObjectType = PathObjectType.Package;

            this.synchronousProxy = synchronousProxy;

            RegisterProperties(package);

            _HydraServiceBase.Disposed += (sender, e) =>
            {
                if (sender == package)
                {
                    if (Disposed != null)
                    {
                        Disposed(this, EventArgs.Empty);
                    }
                }
            };
        }

        public PathRoot(IUnknown service, Guid serviceGuid, ISynchronousProxy synchronousProxy)
        {
            InstanceID = Guid.NewGuid();
            ObjectGuid = serviceGuid;
            ObjectType = PathObjectType.Package;

            this.synchronousProxy = synchronousProxy;

            RegisterProperties(service);

            _HydraServiceBase.Disposed += (sender, e) =>
            {
                if (sender == service)
                {
                    Disposed(this, EventArgs.Empty);
                }
            };
        }

        private void RegisterProperties(object pathObject)
        {
            var properties = pathObject.GetType().GetProperties().Where(p => p.PropertyType.GetInterfaces().Any(i => i == typeof(INotifyCollectionChanged)));

            foreach (var property in properties)
            {
                var getMethod = property.GetGetMethod();
                var collection = (INotifyCollectionChanged)getMethod.Invoke(pathObject, null);
                var expressionProcessorClient = (IExpressionProcessorClient)collection;

                collection.CollectionChanged += (sender, e) =>
                {

                };

                expressionProcessorClient.OnProcessExpression += (XElement element, string path, out object result) =>
                {
                    var formatString = "Element={0}&Path={1}";
                    var updates = synchronousProxy.Call<SynchronizationUpdate[]>("ProcessQuery", formatString, element, path);

                    result = int.Parse(updates[0].SingleValue);
                };

                if (collection is IQueryable)
                {
                    var queryable = ((IQueryable)collection).Cast<object>();
                    var count = queryable.Count();
                }
            }
        }
    }
}
